/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package montecarlo.math;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author alucard
 */
public class montecarlo
{

    private String CallPutFlag;
    private double S;
    private double X;
    private double T;
    private double r;
    private double b;
    private double v;
    private int nSteps;
    private int nSimulations;
    private Random rand;
    private monteCarloHolder mtHolder;

    public montecarlo(String CallPutFlag, double S, double X, double T, double r, double b, double v, int nSteps, int nSimulations)
    {
        this.CallPutFlag = CallPutFlag;
        this.S = S;
        this.X = X;
        this.T = T;
        this.r = r;
        this.b = b;
        this.v = v;
        this.nSteps = nSteps;
        this.nSimulations = nSimulations;
        this.rand = new Random(1234);
    }

    public double monteCarloSingle()
    {

        double dt, St, Sum = 0, Drift, vSqrdt;
        int i, j, z = 0;

        dt = this.T / this.nSteps;
        Drift = (this.b - Math.pow(this.v, 2) / 2) * dt;
        vSqrdt = this.v * java.lang.Math.sqrt(dt);

        if (this.CallPutFlag.equals("c"))
        {
            z = 1;
        } else
        {
            if (this.CallPutFlag.equals("p"))
            {
                z = -1;
            }
        }

        for (i = 1; i < this.nSimulations; i++)
        {
            St = this.S;
            for (j = 1; j < this.nSteps; j++)
            {
                St = St * Math.exp(Drift + vSqrdt * this.rand.nextGaussian());
            }

            Sum = Sum + Math.max(z * (St - this.X), 0);
        }

        return Math.exp(-this.r * this.T) * (Sum / this.nSimulations);
    }

    public void monteCarloMulti(int nb)
    {
        double dt, Sum = 0, Drift, vSqrdt;
        int i, j, z = 0, w;
        ArrayList<monteCarloWorker> mtList = new ArrayList<monteCarloWorker>();

        this.mtHolder = new monteCarloHolder(nb);

        dt = this.T / this.nSteps;
        Drift = (this.b - Math.pow(this.v, 2) / 2) * dt;
        vSqrdt = this.v * java.lang.Math.sqrt(dt);

        if (this.CallPutFlag.equals("c"))
        {
            z = 1;
        } else
        {
            if (this.CallPutFlag.equals("p"))
            {
                z = -1;
            }
        }

        //Setup workers

        for (w = 0; w < nb; w++)
        {
            monteCarloWorker mt = new monteCarloWorker(this.S, Drift, vSqrdt, z, nSteps, nSimulations / nb, X, nb, this.r, this.T, new Random(1234), String.valueOf(w), this.mtHolder);
            mtList.add(mt);
        }
        for (w = 0; w < nb; w++)
        {
            mtList.get(w).start();
            System.out.println("Starting thread : " + w);
        }



    }

    public monteCarloHolder getMtHolder()
    {
        return mtHolder;
    }
}
